﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

/// <summary>
/// This writes out to the logs directory.
/// There are three file types, .err = errors, .log = non errors, .dmp = dump files
/// </summary>
public static class log
{
	public static void Message(string message)
	{
		WriteLine(message, LogFilePath);
	}
	public static void Warning(string message)
	{
		WriteLine("WARNING:"+message, LogFilePath);
	}
	public static void Error(string message)
	{
		WriteLine("ERROR:" + message, ErrLogFilePath);
	}
	private static void WriteLine(string line,string logFilePath)
	{
		File.AppendAllText(logFilePath,DateTime.Now.ToString("HH:MM: ") + line + Environment.NewLine);
	}
	/// <summary>
	/// Calculates a path for a dmp file with the given hash code.
	/// </summary>
	/// <param name="hashCode">The hash code guarentees we don't write the same dump more than once.</param>
	/// <returns></returns>
	private static string GetDmpLogFilePath(int hashCode)
	{
		return Path.Combine(LogDirectory, hashCode.ToString() + ".dmp");
	}
	//private static string m_dmpLogFilePath = null;
	/// <summary>
	/// The err file is more critical than a log file
	/// </summary>
	private static string ErrLogFilePath
	{
		get
		{
			if (m_errLogFilePath == null)
			{
				m_errLogFilePath = Path.Combine(LogDirectory, DateTime.Today.ToString("yyyyMMdd") + ".err");
			}
			return m_errLogFilePath;
		}
	}
	private static string m_errLogFilePath = null;
	/// <summary>
	/// Get the log file path
	/// </summary>
	private static string LogFilePath
	{
		get
		{
			if (m_logFilePath == null)
			{
				m_logFilePath = Path.Combine(LogDirectory, DateTime.Today.ToString("yyyyMMdd")+".log");
			}
			return m_logFilePath;
		}
	}
	private static string m_logFilePath = null;
	/// <summary>
	/// Get the log directory
	/// </summary>
	private static string LogDirectory
	{
		get
		{
			if (m_logDirectory == null)
				m_logDirectory = HttpContext.Current.Server.MapPath("~/logs/");
			return m_logDirectory;
		}
	}
	private static string m_logDirectory;
	private static string GetProductLogDirectory(string productName)
	{
		return Path.Combine(Settings.Product.ProductBaseDirectory, productName, "logs");
	}
	/// <summary>
	/// Picks up and sends the system log files to the subscribers.
	/// </summary>
	/// <param name="productName">Product name</param>
	public static void SendLog( string productName = null,string comment = null)
	{
		string directory = null;
		if (productName == null)
			directory = LogDirectory;
		else
			directory = GetProductLogDirectory(productName);
		string errContents = SendOneTypeOfLog(directory, "err");
		string logContents = SendOneTypeOfLog(directory, "log");
		// We need to send the system logs: .err, .log, .dmp
		foreach (var subscriber in Settings.LogSubscribers.Subscribers)
		{
			System.Text.StringBuilder body = new System.Text.StringBuilder();
			if( (!String.IsNullOrEmpty(errContents) && subscriber.Errs) || (!String.IsNullOrEmpty(logContents) && subscriber.Logs))
			{
				var subject = (productName == null ? "System " : productName) + " logs for " + Settings.SystemMailSettings.Website + " on " + System.DateTime.Now.ToLongDateString() + " at " + System.DateTime.Now.ToLongTimeString();
				body.Append( subject + " " + (comment??"") + ":\n");
				if (subscriber.Errs)
					body.Append(errContents);
				if (subscriber.Logs)
					body.Append(logContents);
				body.Append("\nEND OF LOG FILE CONTENT\n");
				Mail.Simple(subject, body.ToString(), subscriber.Email);
			}
		}
		// Move the log files to the sent directory.
		foreach (var file in Directory.EnumerateFiles(directory, "*.log").Concat(Directory.EnumerateFiles(directory, "*.err")))
		{
			var destination = Path.Combine(Path.GetDirectoryName(file), "sent", Path.GetFileName(file));
			string loadedText = File.ReadAllText(file);
			File.AppendAllText(destination,loadedText);
			File.Delete(file);
		}
		// Move the dmp files to the sent directory.
		foreach (var file in Directory.EnumerateFiles(directory, "*.dmp"))
			File.Move(file, Path.Combine(Path.GetDirectoryName(file), "sent", Path.GetFileName(file)));
	}
	private static string SendOneTypeOfLog(string directory, string extension)
	{
		System.Text.StringBuilder body = new System.Text.StringBuilder();
		foreach (var file in Directory.EnumerateFiles(directory, "*." + extension))
		{
			body.Append("\nLOG FILE: " + Path.GetFileName(file)+"\n");
			var lines = File.ReadAllLines(file);
			foreach (var line in lines)
				body.AppendLine(line);
		}
		return body.ToString();
	}
}